/*
 * Copyright (C) ALi Shanghai Corp. 2004
 *
 * File: lib_as.c
 *
 * Content: auto-scan service implementation for M3327 chip based IRD.
 *
 * History:
 *    Date	Version		Author		Comment
 *    ========	======= 	========	========
 */
#include <types.h>
#include <sys_config.h>
#include <retcode.h>
#include <mediatypes.h>
#include <bus/tsi/tsi.h>
#include <osal/osal.h>
#include <api/libc/alloc.h>
#include <api/libc/string.h>
#include <hld/hld_dev.h>
#include <hld/nim/nim.h>
#include <hld/dmx/dmx_dev.h>
#include <hld/dmx/dmx.h>
#include <api/libnim/lib_nim.h>

#include <api/libdiseqc/lib_diseqc.h>
#include "../as_dvbs.h"
#include "../as_dvbc.h"
#include "../as_dvbt.h"
#include <api/libtsi/p_search.h>
#include <api/libtsi/db_3l.h>
#include <api/libtsi/tmp_info.h>
#include <api/libtsi/siae.h>
#include <api/libtsi/psi_search.h>

#include <api/libpub/lib_pub.h>
#include <api/libpub/as_module.h>



#define AS_DEBUG_LEVEL 			0
#if (AS_DEBUG_LEVEL>0)
#include <api/libc/printf.h>
#define AS_PRINTF			libc_printf
#define AS_SDBBP			SDBBP
#else
#define AS_PRINTF(...)		do{}while(0)
#define AS_SDBBP(...)			do{}while(0)
#endif

#ifdef __MM_VBV_START_ADDR
#ifdef DUAL_ENABLE
#define __MM_AS_START_ADDR		(__MM_EPG_BUFFER_START&0x8FFFFFFF)
#define __MM_PSI_START_ADDR		((__MM_EPG_BUFFER_START&0x8FFFFFFF)+sizeof(struct as_module_info))
#else
#define __MM_AS_START_ADDR		(__MM_VBV_START_ADDR&0x8FFFFFFF)
#define __MM_PSI_START_ADDR		((__MM_VBV_START_ADDR&0x8FFFFFFF)+sizeof(struct as_module_info))
#endif
#else
void *as_buf = NULL;
#define AS_BUF_LEN 0x48000
#define __MM_AS_START_ADDR		((UINT32)as_buf&0x8FFFFFFF)
#define __MM_PSI_START_ADDR		(((UINT32)as_buf&0x8FFFFFFF)+sizeof(struct as_module_info))
#endif

#if (defined(SUPPORT_MTILINGUAL_SERVICE_NAME)||defined(SUPPORT_FRANCE_HD))	
#define __MM_PSI_BUF_LEN        (400*1024)	
#else
#define __MM_PSI_BUF_LEN        (240*1024)
#endif

struct as_module_info *as_info = NULL;//Martin@20150410_ScanFrq
//static struct as_module_info *as_info = NULL;

#if (AS_DEBUG_LEVEL > 0)
static void AS_DUMP_SAT(S_NODE *sat)
{
    AS_PRINTF("***************************************\n");
    AS_PRINTF("* sat id = %d\n", sat->sat_id);
    AS_PRINTF("* sat lnb_type = %d\n", sat->lnb_type);
    AS_PRINTF("* sat lnb_low = %d\n", sat->lnb_low);
    AS_PRINTF("* sat lnb_high = %d\n", sat->lnb_high);
    AS_PRINTF("* sat polar = %d\n", sat->pol);
    AS_PRINTF("***************************************\n");
}

static void AS_DUMP_TP(T_NODE *tp)
{
    AS_PRINTF("***************************************\n");
    AS_PRINTF("* tp id = %d\n", tp->tp_id);
    AS_PRINTF("* tp freq = %d\n", tp->frq);
    AS_PRINTF("* tp sym = %d\n", tp->sym);
    AS_PRINTF("* tp pol = %d\n", tp->pol);
    AS_PRINTF("* tp FEC inner = %d\n", tp->FEC_inner);
    AS_PRINTF("***************************************\n");
}
#else
#define AS_DUMP_SAT(...)			do{}while(0)
#define AS_DUMP_TP(...)			do{}while(0)
#endif
//#ifdef ITALY_HD_BOOK_SUPPORT
#if(defined ITALY_HD_BOOK_SUPPORT ||defined 	POLAND_SPEC_SUPPORT)	
typedef  BOOL (*node_view_init)();
static node_view_init NodeView_InitCallback = NULL;
#endif

#if defined(STAR_PROG_SEARCH_NIT_SDT_SUPPORT)
UINT32 star_search_nit_staus = 0;	// 0: not rec, 1: rec, 2: nit search started
#endif

#ifdef NIT_AUTO_SEARCH_SUPPORT
static BOOL b_found_nit_tp = FALSE; //TRUE: found nit in a tp; FALSE: no
#endif
/*NIt search callback for update tp*/
static UINT8 as_update_tp(TP_INFO *t_info)
{
    INT32 i;

    if(as_info->param.as_frontend_type==FRONTEND_TYPE_S)
    {
        dvbs_tp_info2db(t_info, &as_info->cur_tp);
		//Check whether Current TP Param is Valid or not
    	if(dvbs_tp_sanity_check(as_info->voltage_ctrl, &as_info->cur_tp, &as_info->cur_sat) == FALSE)
    	{
        		return as_info->stop_scan_signal;
    	}
	}
	else if(as_info->param.as_frontend_type == FRONTEND_TYPE_C)
	{
		//Copy Input TP Info to Current TP
    	dvbc_tp_info2db(t_info, &as_info->cur_tp);
	    //Check whether Current TP Param is Valid or not
    	if(dvbc_tp_sanity_check(FALSE, &as_info->cur_tp, NULL) == FALSE)
    	{
        		return as_info->stop_scan_signal;
    	}
	}
	else if(as_info->param.as_frontend_type == FRONTEND_TYPE_T)
    	{    		
#if (defined(STAR_PROG_SEARCH_NIT_SDT_SUPPORT) || defined(COMBOUI))
			//Copy Input TP Info to Current TP
        	dvbt_tp_info2db(t_info, &as_info->cur_tp);
		//Check whether Current TP Param is Valid or not
        	if(dvbt_tp_sanity_check(FALSE, &as_info->cur_tp, NULL) == FALSE)
        	{
            		return as_info->stop_scan_signal;
        	}
#endif
	}

	//Search TP Info in DB. If can't find, then Add this TP Info into DB
    	as_info->cur_tp.sat_id = as_info->cur_sat.sat_id;
    	if(db_search_lookup_node(TYPE_SEARCH_TP_NODE, &as_info->cur_tp) != SUCCESS)
    	{
#ifdef STAR_PROG_SEARCH_NIT_SDT_SUPPORT
			as_info->cur_tp.pat_version = 0xff;
#endif			
        	if(add_node(TYPE_SEARCH_TP_NODE,as_info->cur_tp.sat_id, &as_info->cur_tp) == STORE_SPACE_FULL)
        	{
            		return 1;
        	}
    	}

    	AS_DUMP_TP(&as_info->cur_tp);
	//Search Current TP in Waiting Scan TP List, if find, then Return, otherwise Add Current TP 
	//to Waiting Scan TP List
#ifndef 	STAR_PROG_SEARCH_NIT_SDT_SUPPORT
    	for(i = as_info->tp_nr - 1; i >= 0; i--)
    	{
        	if (as_info->tp_id[i] == as_info->cur_tp.tp_id)
        	{
            		return as_info->stop_scan_signal; 
        	}
	}		
#endif

    	as_info->tp_id[as_info->tp_nr++] = as_info->cur_tp.tp_id;
#ifdef NIT_AUTO_SEARCH_SUPPORT// add for auto scan with nit search 
	if(as_info->atp.nit_enable == 1 && as_info->tp_nr > 0)
		b_found_nit_tp = TRUE;
	else 
		b_found_nit_tp = FALSE;
#endif

#if defined(STAR_PROG_SEARCH_NIT_SDT_SUPPORT)
		if(star_search_nit_staus==0)//set receive nit flag
			star_search_nit_staus = 1;
#endif		

	if(as_info->param.as_handler != NULL)
    	{
        	as_info->param.as_handler(ASM_TYPE_INC_TRANSPONDER, 0);
    	}

    	return as_info->stop_scan_signal; 
}



/*description	: transpoder program search update callback.*/
static UINT8 psi_callback(UINT8 progress, void *param)
{
    UINT16 pg_pos;

    //nit scan update tp
    if (progress>=AS_PROGRESS_NIT)
    {
    	if(progress==AS_PROGRESS_NIT_TP_CNT)
    	{
    		UINT16 tp_cnt = *((UINT16 *)param);
    		
    		if(as_info->param.as_handler!=NULL)
    			as_info->param.as_handler(ASM_TYPE_NIT_TP_CNT, tp_cnt);
    		return as_info->stop_scan_signal;
    	}
#ifdef STAR_PROG_SEARCH_NIT_SDT_SUPPORT
	else if(AS_PROGRESS_SEARCH_MODE_UPDATE == progress)
	{
		UINT16 search_mode = *((UINT16 *)param);
		
		if(as_info->param.as_handler!=NULL)
			as_info->param.as_handler(ASM_TYPE_SEARCH_MODE_CHANGE, search_mode);
		return as_info->stop_scan_signal;
    			
	}
#endif			
    	return as_update_tp((TP_INFO *)param);
    }
    else if (progress!=AS_PROGRESS_NIT_VER_CHANGE)
    {
        if (param)
        {
            P_NODE *p_node = (P_NODE *)param;
            
            	//#ifdef ITALY_HD_BOOK_SUPPORT
		#if(defined ITALY_HD_BOOK_SUPPORT ||defined 	POLAND_SPEC_SUPPORT)	
			pg_pos = PostProcessing_GetProgIdx(p_node);
		#else
            		pg_pos = get_prog_pos(p_node->prog_id);
		#endif

            if(as_info->param.as_handler!=NULL)
    		{
    			as_info->param.as_handler(ASM_TYPE_ADD_PROGRAM, pg_pos);
    		}
        }

		if ((as_info->param.as_method == AS_METHOD_TP) && (as_info->param.as_handler != NULL))
		{
    		as_info->param.as_handler(ASM_TYPE_PROGRESS, progress);
		}
	}
	else if(progress==AS_PROGRESS_NIT_VER_CHANGE)
	{
		if(as_info->param.as_handler!=NULL)
			as_info->param.as_handler(ASM_TYPE_NIT_VER_CHANGE, *((UINT8 *)param));
		return as_info->stop_scan_signal;
	}

	return as_info->stop_scan_signal;
}

/* According to input as info and tp info, set anntenna and nim of frontend */
static UINT32 as_frontend_tuning(struct as_module_info *info, T_NODE *tp)
{
    UINT32 time_out = 0;
	union ft_xpond *xponder = &info->xponder;
	struct ft_antenna *antenna = &info->antenna;

	//Set TP Info for DVB-S/C/T
	MEMSET(xponder, 0, sizeof(union ft_xpond));

	if(tp->ft_type == FRONTEND_TYPE_S)
	{
    	time_out = AS_TUNE_TIMEOUT_S*40;// when signal quality is low, TP scan need wait a long time to lock it.
    	xponder->s_info.type = tp->ft_type;
    	xponder->s_info.tp_id = tp->tp_id;
    	xponder->s_info.frq = tp->frq;
    	xponder->s_info.sym = tp->sym;
    	xponder->s_info.pol = tp->pol;
    	xponder->s_info.fec_inner = tp->FEC_inner;
	}
	else if(tp->ft_type == FRONTEND_TYPE_C)
	{
    	time_out = AS_TUNE_TIMEOUT_C;
    	xponder->c_info.type = tp->ft_type;
    	xponder->c_info.tp_id = tp->tp_id;
    	xponder->c_info.frq = tp->frq;
    	xponder->c_info.sym = tp->sym;
	//FEC_inner store modulation in this case
    	xponder->c_info.modulation = tp->FEC_inner;
	}
	else if((tp->ft_type == FRONTEND_TYPE_T))
	{
				time_out = AS_TUNE_TIMEOUT_C;
				xponder->t_info.type = tp->ft_type;
				//xponder->t_info.tp_id = tp->tp_id;
				xponder->t_info.frq = tp->frq;
#ifdef COMBOUI				
				xponder->t_info.band_width = tp->bandwidth*1000;
#endif			
				xponder->t_info.usage_type = (UINT8)USAGE_TYPE_CHANSCAN; //channel scan

	}

    if(tp->ft_type == FRONTEND_TYPE_S)
    {
        //Set Antenna
	    frontend_set_antenna(as_info->nim, antenna, xponder, 1);
        //Set NIM
	    frontend_set_nim(as_info->nim, antenna, xponder, 1);
    }
    else
    {
        frontend_set_nim(as_info->nim, NULL, xponder, 1);
    }
		if((tp->ft_type == FRONTEND_TYPE_T))
		{
			UINT8 lock_stat;
			UINT8 nim_value;
			
#ifdef STAR_PROG_SEARCH_NIT_SDT_SUPPORT
			osal_task_sleep(500);
#else
			osal_task_sleep(1000);
#endif
			nim_get_lock(as_info->nim, &lock_stat);
			if(lock_stat)
			{
				//according info->nim device to get info
			if(NULL != info->nim->do_ioctl)
			{
            #ifdef COMBOUI
                info->nim->do_ioctl(info->nim, NIM_DRIVER_GET_GUARD_INTERVAL, (UINT32)&nim_value);
                tp->guard_interval=nim_value;
								info->nim->do_ioctl(info->nim, NIM_DRIVER_GET_FFT_MODE, (UINT32)&nim_value);   
                tp->FFT = nim_value;
                info->nim->do_ioctl(info->nim, NIM_DRIVER_GET_MODULATION, (UINT32)&nim_value);
                tp->modulation = nim_value;
                info->nim->do_ioctl(info->nim, NIM_DRIVER_GET_SPECTRUM_INV, (UINT32)&nim_value);
                tp->inverse = nim_value;
						#endif
        }	
				nim_get_FEC(info->nim, &nim_value);
				tp->FEC_inner = nim_value;
#if defined(DVBT2_SUPPORT)
            tp->t2_signal = xponder->t_info.t2_signal;
            tp->plp_index = xponder->t_info.plp_index;
            tp->plp_id = xponder->t_info.plp_id;
            tp->t2_system_id = xponder->t_info.t2_system_id;
            tp->t2_profile = xponder->t_info.t2_profile;
        	if ( db_search_lookup_node(TYPE_SEARCH_TP_NODE, tp) != SUCCESS )
             {
        		if ( add_node(TYPE_SEARCH_TP_NODE, tp->sat_id, tp) != SUCCESS )
        			return FALSE;
        	}
            else  
            {
//            	get_tp_by_id(t_node.tp_id, &temp_t_node);
    			modify_tp(tp->tp_id, tp);
            }
			update_data();
            
			xponder->t_info.tp_id = tp->tp_id;
            info->atp.tp_id = tp->tp_id;
#else
			modify_tp(tp->tp_id, tp);
			update_data();
#endif
		}
	}
	return time_out;
}

/* Set as info(including tp id, timeout, and so on) for one specific tp */
static void as_dvbs_preset_tuning(void *param)
{
    struct as_tuning_param *atp;
    T_NODE *tp;
    atp = (struct as_tuning_param *)param;

    if (atp->finish == TRUE)
	{
    	return;
	}
    while ((INT32)atp->pos <= as_info->tp_nr)
    {
        tp = &as_info->xp;
        if (get_tp_by_id(as_info->tp_id[atp->pos], tp)!=SUCCESS)
    	{
        		break;
    	}
        atp->nit_enable = as_info->tp_nit[atp->pos];
        atp->tp_id = as_info->tp_id[atp->pos++];
        atp->timeout = as_frontend_tuning(as_info, tp) + osal_get_tick();
        return;
    }
    atp->finish = TRUE;
}
#if defined(DVBT2_SUPPORT)
static UINT32 as_next_pipe_tuning(struct as_module_info *info, T_NODE *tp)
{
    //Try to auto detect the next signal pipe within this channel, 
    //such as the next PLP of (MPLP of DVB-T2), or the next priority signal(Hierarchy of DVB-T).
    //Before USAGE_TYPE_NEXT_PIPE_SCAN can be used, you must call USAGE_TYPE_AUTOSCAN or USAGE_TYPE_CHANSCAN first.
    
	UINT8 pre_plp_index;
    UINT8 lock_stat;
	UINT8 nim_value;
	union ft_xpond *xponder = &info->xponder;   //It's shall keep the result returned by call USAGE_TYPE_AUTOSCAN or USAGE_TYPE_CHANSCAN.

	if(info->stop_scan_signal)
        return FALSE;
    
	if(tp->ft_type != FRONTEND_TYPE_T)
        return FALSE;
    
	if(xponder->t_info.t2_signal == 0)  //DVB-T
	{
        //If need to support Hierarchy of DVB-T, you can tune to the next priority signal at here. 
        return FALSE;
	}
    
    //(DVBT2_SUPPORT)
    //It's DVB-T2 now.
	if(xponder->t_info.plp_num == 0)  //Unlocked.
	{
        return FALSE;
	}
    pre_plp_index = xponder->t_info.plp_index;
	xponder->t_info.usage_type = (UINT8)USAGE_TYPE_NEXT_PIPE_SCAN;
    frontend_set_nim(info->nim, NULL, xponder, 1);

    if (pre_plp_index == xponder->t_info.plp_index) //No data PLP can be locked.
        return FALSE;
			
    //Bug fixed: Search a bad config MPLP signal, it maybe unstable, sometime a program be stored with the previous PLP setting.
    //Do not need to check whether the signal is locked at here, because maybe it can be locked later.
    //Otherwise if correct PLP can not be locked now, then the PLP setting dost not be updated, and keep the previous locked PLP setting. 
//	nim_get_lock(info->nim, &lock_stat);
//	if( ! lock_stat)
//  {
//      libc_printf("%s() error: unlock\r\n", __FUNCTION__);
//	}
    
	{

        tp->t2_signal = xponder->t_info.t2_signal;
        tp->plp_index = xponder->t_info.plp_index;
        tp->plp_id = xponder->t_info.plp_id;
        tp->t2_system_id = xponder->t_info.t2_system_id;
        tp->t2_profile = xponder->t_info.t2_profile;
		  

    	if ( db_search_lookup_node(TYPE_SEARCH_TP_NODE, tp) != SUCCESS )
         {
    		if ( add_node(TYPE_SEARCH_TP_NODE, tp->sat_id, tp) != SUCCESS )
    			return FALSE;
    	}
        else  
        {
//          get_tp_by_id(t_node.tp_id, &temp_t_node);
			modify_tp(tp->tp_id, tp);
        }
		update_data();
        
		xponder->t_info.tp_id = tp->tp_id;
        info->atp.tp_id = tp->tp_id;
	}
	return TRUE;
}
#endif

/*DVBC blind scan in fact is tp scan by bandwith step*/
#if defined DVBC_COUNTRY_BAND_SUPPORT || defined COMBOUI
static UINT32 c_srh_tp_step = 0;
static UINT32 dvbc_bs_freq_end = 0;
static void as_dvbc_blind_tuning(void *param)
{
	struct as_tuning_param *atp = (struct as_tuning_param *)param;
	union ft_xpond xponder;

	UINT32 cnt_finish=0, cnt_band=0, cnt_ttl=0,index=0;

	//If Blind Scan Already Finished, then Return
	if(dvbc_bs_freq_end)
		atp->finish = TRUE;

	if (atp->finish == TRUE)
	{
		return;
	}

	MEMSET(&xponder, 0, sizeof(xponder));
	xponder.common.type = atp->ft_type = as_info->param.as_frontend_type;
	if(atp->ft_type==FRONTEND_TYPE_C)
	{
        atp->ft.c_param.sym = as_info->param.ft[atp->ft_count].c_param.sym;
        atp->ft.c_param.constellation = as_info->param.ft[atp->ft_count].c_param.constellation;

        xponder.c_info.frq = atp->pos;
        xponder.c_info.sym = atp->ft.c_param.sym;                   // as_info->param.ft.c_param.sym;
        xponder.c_info.modulation = atp->ft.c_param.constellation;	// as_info->param.ft.c_param.constellation;
	}

	//libc_printf("as_dvbc_blind_tuning frq:%d sym:%d modulation:%d timeout:%d\n",
	//	xponder.c_info.frq, xponder.c_info.sym,  xponder.c_info.modulation, atp->timeout);

	frontend_set_nim(as_info->nim, NULL, &xponder, 1);

	if(as_info->param.as_handler)
	{
		//as_info->param.as_handler(ASM_TYPE_SCANNING_INFO,1+c_srh_tp_step+((atp->cur_band&0x7f)<<8));

		for(index = 0; index < atp->band_count; index++)
		{
			cnt_band = 1+ atp->band_group_param[index].end_ch_no - atp->band_group_param[index].start_ch_no;

             //if(as_info->param.ft_count > 1)
             cnt_band *= as_info->param.ft_count;
			cnt_ttl += cnt_band;

			if(atp->cur_band>index)
				cnt_finish += cnt_band;
		}

         if(c_srh_tp_step != 0)
         {
            if(atp->ft_count == as_info->param.ft_count-1)
                 cnt_finish += c_srh_tp_step;
            else
                cnt_finish += (c_srh_tp_step - (as_info->param.ft_count-1 - atp->ft_count));
         }

		as_info->param.as_handler(ASM_TYPE_PROGRESS, 100*cnt_finish/cnt_ttl);
	}
	c_srh_tp_step++;

     if(as_info->param.ft_count > 1)
     {
        if(atp->cur_band < atp->band_count)
        {
            if(atp->ft_count < as_info->param.ft_count-1)
            {
                atp->ft_count++;
                //atp->ft.c_param.sym = as_info->param.ft[atp->ft_count].c_param.sym;
                //atp->ft.c_param.constellation = as_info->param.ft[atp->ft_count].c_param.constellation;
                atp->timeout = osal_get_tick()+ AS_TUNE_TIMEOUT_C;
                return;
            }
            else
            {
                atp->ft_count = 0;
               // atp->ft.c_param.sym = as_info->param.ft[0].c_param.sym;
               // atp->ft.c_param.constellation = as_info->param.ft[0].c_param.constellation;
            }
        }
    }

	while(atp->cur_band < atp->band_count)
	{
		if(atp->pos+atp->step <= atp->limit)
		{
			atp->timeout = osal_get_tick()+ AS_TUNE_TIMEOUT_C;
			atp->pos += atp->step;

			if(atp->start == atp->limit && atp->step==0) // only one frequency in this band
				atp->step = 1;
			return;
		}
		atp->cur_band++;
		if(atp->cur_band < atp->band_count)
		{
			atp->start = atp->band_group_param[atp->cur_band].start_freq;
			atp->limit = atp->band_group_param[atp->cur_band].end_freq;
			atp->step = atp->band_group_param[atp->cur_band].freq_step;
			atp->pos = atp->start- atp->step;
			c_srh_tp_step = 0;
		}
	}

	//if ((atp->pos < atp->limit) && (as_info->param.as_handler))
	//{
	//		as_info->param.as_handler(ASM_TYPE_PROGRESS, 99*(atp->pos-atp->start)/(atp->limit-atp->start));
	//}

	atp->timeout += AS_TUNE_TIMEOUT_C; // for the last frequency
	dvbc_bs_freq_end = 1;

}
#else
/*DVBC and DVBT blind scan in fact is tp scan by bandwith step*/
static void as_dvbc_blind_tuning(void *param)
{
    	struct as_tuning_param *atp = (struct as_tuning_param *)param;
    	union ft_xpond xpond;

	//If Blind Scan Already Finished, then Return
    	if (atp->finish == TRUE)
    	{
        	return;
    	}

    MEMSET(&xpond, 0, sizeof(xpond));
    xpond.common.type = atp->ft_type = as_info->param.as_frontend_type;
    if(atp->ft_type==FRONTEND_TYPE_C)
    {
        xpond.c_info.frq = atp->pos;
        xpond.c_info.sym = as_info->param.ft.c_param.sym;
        xpond.c_info.modulation = as_info->param.ft.c_param.constellation;
    }
    else if(atp->ft_type==FRONTEND_TYPE_T)
    {

    }
    
    while(atp->pos <= atp->limit)
    {
        frontend_set_nim(as_info->nim, NULL, &xpond, 1);
	if((atp->ft_type==FRONTEND_TYPE_C) &&(as_info->param.as_handler))
	{
		as_info->param.as_handler(ASM_TYPE_INC_TRANSPONDER,atp->pos);
	}
        atp->timeout = osal_get_tick()+ AS_TUNE_TIMEOUT_C;
        atp->pos += atp->step;
        if(atp->ft_type==FRONTEND_TYPE_C)
        {
            if ((atp->pos>DVBC_FREQUENCY_VHF_HIGH)&&(atp->pos<DVBC_FREQUENCY_UHF_LOW))
            {
                		if (atp->limit >= DVBC_FREQUENCY_UHF_LOW)
                		{
                    			atp->pos = DVBC_FREQUENCY_UHF_LOW;
                		}
				else
				{
                    			return;
				}
            		}
        	}

        	if ((atp->pos < atp->limit) && (as_info->param.as_handler))
        	{
            		as_info->param.as_handler(ASM_TYPE_PROGRESS, 99*(atp->pos-atp->start)/(atp->limit-atp->start));
        	}
   
        return;
    }
    atp->finish = TRUE;
}
#endif

static UINT32 t_srh_tp_step = 0;
static UINT32 dvbt_bs_freq_end = 0;
/*DVBT blind scan in fact is tp scan by bandwith step*/
static void as_dvbt_blind_tuning(void *param)
{
	struct as_tuning_param *atp = (struct as_tuning_param *)param;
	union ft_xpond *xponder = &as_info->xponder;
	UINT32 cnt_finish=0, cnt_band=0, cnt_ttl=0,index=0;

	//If Blind Scan Already Finished, then Return
	if(dvbt_bs_freq_end)
		atp->finish = TRUE;
	
	if (atp->finish == TRUE)
	{
		return;
	}	

	//If no NIT tp is found, just move forward step by step
#if defined(STAR_PROG_SEARCH_NIT_SDT_SUPPORT)
	if(0 == star_search_nit_staus) 
#endif
	{
	MEMSET(xponder, 0, sizeof(union ft_xpond));
	xponder->common.type = atp->ft_type = as_info->param.as_frontend_type;
	if(atp->ft_type==FRONTEND_TYPE_T)
	{
		xponder->t_info.type = atp->ft_type;
		//xponder->t_info.tp_id = tp->tp_id;
		xponder->t_info.frq = atp->pos;
		xponder->t_info.band_width = atp->step;		
		xponder->t_info.usage_type = (UINT8)USAGE_TYPE_AUTOSCAN; //auto scan
	}
	frontend_set_nim(as_info->nim, NULL, xponder, 1);

	if(as_info->param.as_handler)
	{
	#ifdef COMBOUI
		as_info->param.as_handler(ASM_TYPE_SCANNING_INFO,1+t_srh_tp_step+((atp->cur_band&0x7f)<<8));

		for(index = 0; index < atp->band_count; index++)
		{
			cnt_band = (atp->band_group_param[index].end_freq  - atp->band_group_param[index].start_freq)/atp->band_group_param[index].bandwidth;
			cnt_ttl += cnt_band;
			if(atp->cur_band>index)
				cnt_finish += cnt_band;
		}
		cnt_finish += t_srh_tp_step;
		
		as_info->param.as_handler(ASM_TYPE_PROGRESS, 100*cnt_finish/cnt_ttl);
	#endif	
	}
	t_srh_tp_step++;
	
	#ifdef COMBOUI
	while(atp->cur_band < atp->band_count)
	{
		atp->timeout = osal_get_tick()+ AS_TUNE_TIMEOUT_T;
		if(atp->pos+atp->step < atp->limit)
		{
			atp->pos += atp->step;
			return;
		}
		atp->cur_band++;
		if(atp->cur_band < atp->band_count)
		{
			atp->start = atp->band_group_param[atp->cur_band].start_freq+atp->band_group_param[atp->cur_band].bandwidth/2;
			atp->limit = atp->band_group_param[atp->cur_band].end_freq+atp->band_group_param[atp->cur_band].bandwidth/2;
			atp->step = atp->band_group_param[atp->cur_band].bandwidth;
			atp->pos = atp->start - atp->step;
			t_srh_tp_step = 0;
		}
	}
	#endif

	//if ((atp->pos < atp->limit) && (as_info->param.as_handler))
	//{
	//		as_info->param.as_handler(ASM_TYPE_PROGRESS, 99*(atp->pos-atp->start)/(atp->limit-atp->start));
	//}
	}
#if defined(STAR_PROG_SEARCH_NIT_SDT_SUPPORT)
	else//if found NIT table during blind scan, jump to NIT TP list
	{
		if(star_search_nit_staus != 2)
		{
			star_search_nit_staus = 2;
			atp->pos = 0;
		}
	
		//20110909, fix blind scan issue. for atp->pos will ++ in as_dvbs_preset_tuning.
		//so after as_dvbs_preset_tuning, atp->pos is next one, not current one!
		if(atp->pos < as_info->tp_nr)
			as_info->param.as_handler(ASM_TYPE_PROGRESS, (100*atp->pos)/(as_info->tp_nr));

		as_dvbs_preset_tuning(atp);

		//20110909, fix blind scan issue.	
		//as_info->param.as_handler(ASM_TYPE_PROGRESS, (100*atp->pos)/(as_info->tp_nr));

		return;
		
	}
#endif	
	dvbt_bs_freq_end = 1;	
}

BOOL dvbt_init_search_param(struct as_service_param *param, struct as_tuning_param *atp)
{
#ifdef COMBOUI
	if(param->scan_cnt<1 || param->scan_cnt>MAX_BAND_COUNT)
	{
		atp->finish = TRUE;
		return FALSE;
	}
	atp->ft_type = param->as_frontend_type;

	atp->start = param->band_group_param[0].start_freq+param->band_group_param[0].bandwidth/2;
	atp->limit = param->band_group_param[0].end_freq+param->band_group_param[0].bandwidth/2;
	atp->step = param->band_group_param[0].bandwidth;
	atp->cur_band=0;

	atp->pos = atp->start;
	atp->band_count = param->scan_cnt;

	atp->band_group_param = param->band_group_param;
#endif

	atp->finish = FALSE;
	t_srh_tp_step = 0;
	dvbt_bs_freq_end = 0;
	return TRUE;
}

///add for poland and france_hd book to get signal of tp
#if(defined(POLAND_SPEC_SUPPORT)||defined(SUPPORT_FRANCE_HD))
static get_signal_of_tp(T_NODE *tp)
{
//for saving intensity&quality when chan scan
	UINT8 agc_buffer[10];
	UINT8 snr_buffer[10];
    UINT16 i,agc_sigma=0,snr_sigma=0;;
    UINT8 nim_value1=0,nim_value2=0;

	for(i=0;i<10;i++)
	{
		as_info->nim->get_AGC(as_info->nim, (UINT8*)&nim_value1);
		as_info->nim->get_SNR(as_info->nim, (UINT8*)&nim_value2);

		agc_buffer[i]=nim_value1;
		snr_buffer[i]=nim_value2; 

		osal_task_sleep(15); 
		agc_sigma+=agc_buffer[i];
		snr_sigma+=snr_buffer[i];
	}
	
	tp->intensity= agc_sigma/10;
	tp->quality= snr_sigma/10;
    modify_tp(tp->tp_id, tp);
	//libc_printf("%s: frequency is %d,intensity is %d\n",__FUNCTION__,tp->frq,tp->intensity );

}
#endif
BOOL dvbt_alloc_transponder(struct as_module_info *info,
	struct as_tuning_param *atp, T_NODE *tp, UINT16 sat_id)
{
	INT32 ret;
	UINT32 freq;
	INT32 search_ret;
	UINT8 nim_value;
	union ft_xpond* xpond = &(info->xponder);
	
	MEMSET(tp, 0, sizeof(T_NODE));
	tp->sat_id = sat_id;
	tp->ft_type = FRONTEND_TYPE_T;
	nim_get_freq(info->nim, &freq);

#if defined(DVBT2_SUPPORT)
	tp->priority = xpond->t_info.priority;
	tp->t2_signal = xpond->t_info.t2_signal;
	tp->plp_index = xpond->t_info.plp_index;
	tp->plp_id = xpond->t_info.plp_id;
	tp->t2_profile = xpond->t_info.t2_profile;
#endif

    //If offset is less than 0.4MHz,delete the offset,or add up to 1MHz.
    //So we just show integer(MHz).
    if(freq%100<=40)
        tp->frq = freq/100*100;
    else
        tp->frq = freq/100*100+100;
	tp->frq = freq;
#ifdef COMBOUI
#if 0
	tp->bandwidth = (atp->step)/1000; // atp param not correct this time.
#else
	tp->bandwidth = (xpond->t_info.band_width)/1000;
#endif
	//according info->nim device to get info
	//nim_get_gi(info->nim, &nim_value);
    if(NULL != info->nim->do_ioctl)
    {
        info->nim->do_ioctl(info->nim, NIM_DRIVER_GET_GUARD_INTERVAL, (UINT32)&nim_value);
        tp->guard_interval=nim_value;
        info->nim->do_ioctl(info->nim, NIM_DRIVER_GET_FFT_MODE, (UINT32)&nim_value);   
        tp->FFT = nim_value;
        info->nim->do_ioctl(info->nim, NIM_DRIVER_GET_MODULATION, (UINT32)&nim_value);
        tp->modulation = nim_value;
        info->nim->do_ioctl(info->nim, NIM_DRIVER_GET_SPECTRUM_INV, (UINT32)&nim_value);
        tp->inverse = nim_value;
    }   
	
	nim_get_FEC(info->nim, &nim_value);
	tp->FEC_inner = nim_value;
	tp->band_type = ((atp->band_group_param[atp->cur_band].band_type & 0x80)==0x80)?1:0;
#endif
	search_ret =db_search_lookup_node(TYPE_SEARCH_TP_NODE, tp);
	if ( search_ret != SUCCESS)
     {
#ifdef STAR_PROG_SEARCH_NIT_SDT_SUPPORT
    	tp->pat_version = 0xff;
#endif   
		ret = add_node(TYPE_SEARCH_TP_NODE, tp->sat_id, tp);
		if (ret!=SUCCESS)
			return FALSE;
	}
	#if(defined(POLAND_SPEC_SUPPORT)||defined(SUPPORT_FRANCE_HD))
    get_signal_of_tp(tp);
	#endif
	atp->tp_id = tp->tp_id;
	return TRUE;
}


/****dvbs blind scan**********************************************/

//for tuner to select the nim device
static INT32 as_select_nim(S_NODE *snode, UINT8 front_end_type)
{
    INT32 res = SUCCESS;
	UINT8 nim_id = 0;         //0 or 1
    UINT8 i;
    struct nim_device * nim = NULL; 


    if(FRONTEND_TYPE_S == front_end_type)
    {
        if(snode->tuner1_valid == 1)
        {
    		nim_id = 0;
            tsi_select(TSI_DMX_0, ts_route_get_nim_tsiid(nim_id));
            as_info->nim = (struct nim_device *)dev_get_by_id(HLD_DEV_TYPE_NIM, nim_id);
        }
        else if(snode->tuner2_valid == 1)
        {
    		nim_id = 1;
        	tsi_select(TSI_DMX_0, ts_route_get_nim_tsiid(nim_id));
        	as_info->nim = (struct nim_device *)dev_get_by_id(HLD_DEV_TYPE_NIM, nim_id);
        } 
    }
    else
    {
        for(i=0; i<2; i++)
        {
            nim = (struct nim_device *)dev_get_by_id(HLD_DEV_TYPE_NIM, i);
            if(NULL != nim)
            {
                if(front_end_type == dev_get_device_sub_type(nim, HLD_DEV_TYPE_NIM))
                {
                    tsi_select(TSI_DMX_0, ts_route_get_nim_tsiid(i));
                    as_info->nim = nim;
                    return res;
                }
            }
        }

        nim_id = 0;
        as_info->nim = (struct nim_device *)dev_get_by_id(HLD_DEV_TYPE_NIM, nim_id);
        return res;        
    }
    
#if  0
    if(2 > dev_get_device_cnt(HLD_DEV_TYPE_NIM, FRONTEND_TYPE_S))
    {
		nim_id = 0;
        tsi_select(TSI_DMX_0, ts_route_get_nim_tsiid(nim_id));
        as_info->nim = (struct nim_device *)dev_get_by_id(HLD_DEV_TYPE_NIM, nim_id);
        return res;
    }

    if(snode->tuner1_valid == 1)
    {
		nim_id = 0;
        tsi_select(TSI_DMX_0, ts_route_get_nim_tsiid(nim_id));
        as_info->nim = (struct nim_device *)dev_get_by_id(HLD_DEV_TYPE_NIM, nim_id);
    }
    else if(snode->tuner2_valid == 1)
    {
		nim_id = 1;
    	tsi_select(TSI_DMX_0, ts_route_get_nim_tsiid(nim_id));
    	as_info->nim = (struct nim_device *)dev_get_by_id(HLD_DEV_TYPE_NIM, nim_id);
    }
    else
    {
        nim_id = 0;
        as_info->nim = (struct nim_device *)dev_get_by_id(HLD_DEV_TYPE_NIM, nim_id);
        return res;
    }
    return res;
#endif
}


//dvbs blind scan nim api callback function.
static INT32 dvbs_as_callback(UINT8 signal, UINT8 polar, UINT32 freq, UINT32 sym, UINT8 fec)
{
    static INT16 crnum;
    T_NODE *tp;
    UINT16 sat_id;
    as_update_event_t handle = as_info->param.as_handler;
    UINT8 progress = 0;
    
    if (NULL == as_info)
    {
       	AS_PRINTF("%s: wrong status!\n", __FUNCTION__);
       	return 2;
    }
	    	
    if(as_info->stop_scan_signal)
    {
       	return 2;
    }
    else if((signal == AS_SGN_UNLOCKED) || (signal == AS_SGN_LOCKED))
    {
       	/* Patches for lib_nim Out-Band Xponder Mis-Report */
        //Romn Fix BUG50807 BUG51239
       	if ((signal == AS_SGN_UNLOCKED) || ((crnum < 0) && ((freq < as_info->param.as_from) || (freq > as_info->param.as_to))))
       	{
           	return 0;
       	}
       	else if ((as_info->param.as_method == AS_METHOD_FFT) || (as_info->param.as_method == AS_METHOD_MULTI_FFT))
       	{
       		//Calculate and Show Scan Progress
       		progress = (UINT8)dvbs_calculate_progress(as_info, freq, polar, crnum);
       		if(handle != NULL)
       		{
           		handle(ASM_TYPE_PROGRESS, progress);
       		}
       	}
    }
	
    switch(signal)
    {
    	case AS_SGN_LOCKED:
    		//Check whether New Freq Point, Sym Rate, and Polarity is same to the Old TP or not 
    		if (dvbs_tp_duplicate_check(freq, sym, polar) == FALSE)
    		{
                break;
    		}

    		//Construct one New TP according to Locked Freq and Sym
    		tp = &as_info->xp;
            MEMSET(tp, 0, sizeof(T_NODE));
            dvbs_convert_freq(as_info, tp, freq);
            tp->sym = sym;
            tp->sat_id = sat_id = as_info->cur_sat.sat_id;
            tp->ft_type = FRONTEND_TYPE_S;
            
            AS_DUMP_TP(tp);
            if(db_search_lookup_node(TYPE_SEARCH_TP_NODE, tp)!=SUCCESS)
            {
                INT32 ret;
                ret = add_node(TYPE_SEARCH_TP_NODE, tp->sat_id, tp);
                if ((DBERR_FLASH_FULL==ret) || (DBERR_MAX_LIMIT)==ret)
        		{
            		return 1;
        		}
        	}
    		//Process by Upper Layer	
        	if(handle != NULL)
        	{
            	handle(ASM_TYPE_ADD_TRANSPONDER, tp->tp_id);
        	}

		#ifdef NIM_S3501_ASCAN_TOOLS
		extern UINT32 nim_s3501_ascan_get_scan_tp_only();
		 if(nim_s3501_ascan_get_scan_tp_only()) 
			return 0;
		#endif

            /* start searching si information of all programs in this frequency point  */
       		psi_module_init(as_info->dmx, as_info->nim,(void *)__MM_PSI_START_ADDR, __MM_PSI_BUF_LEN);
#ifdef COMBOUI
			psi_set_search_ftype(as_info->param.as_frontend_type);
			INT32 ret2;
	        ret2 = psi_search_start(sat_id,tp->tp_id, as_info->param.as_prog_attr,\
                        as_info->param.as_p_add_cfg, psi_callback,NULL, NULL);
            handle(ASM_TYPE_ADD_TRANSPONDER, 0); //notify ap that finished search a TP.           
            if (SI_STOFULL == ret2)
            {
            	return 1;
            }
#else
            if (SI_STOFULL == psi_search_start(sat_id,tp->tp_id, as_info->param.as_prog_attr,
                as_info->param.as_p_add_cfg, psi_callback,NULL, NULL))
            {
                return 1;
            }
#endif    	 	 
        break;
    
        case AS_SGN_STOP:
            AS_PRINTF(">>>>>>>>>>>>>>STOP!!!<<<<<<<<<<<<<<<<<<\n");
            as_info->stop_scan_signal=1;
        break;
        
        case AS_SGN_CRNUM:
            crnum = freq;
        break;
        
        case AS_SGN_INIT:
            crnum = -1;
    		//Initialize one TP	
            dvbs_tp_duplicate_check(0, 0, 0);
            break;
    //>>> Unicable begin
    	case AS_SET_UNICABLE:
    		tp = &as_info->xp;
            MEMSET(tp, 0, sizeof(T_NODE));
    		dvbs_convert_freq(as_info, tp, freq);
    		as_info->xponder.s_info.frq = tp->frq;
    		as_info->xponder.s_info.pol = as_info->polar;
    		frontend_set_unicable(as_info->nim,&as_info->antenna, &as_info->xponder);
    		break;
    //<<< Unicable end
        default:
            break;
        }

        return (as_info->stop_scan_signal)? 2: 0;
}

static INT32 as_dvbs_blind_scan(struct ft_antenna *antenna)
{
    UINT32 from = as_info->param.as_from;
    UINT32 to = as_info->param.as_to;	
    UINT32 loop = 0;
    INT32 ret = SUCCESS;
    struct NIM_Auto_Scan *as_para = &as_info->nim_para;

    MEMSET(&(as_info->xponder),0,sizeof(union ft_xpond));
    //as_info->polar: 0-H;1-V. antenna->pol: 0-auto;1-H;2-V
    //for single lnb,scan IF from 950~2150
    if(antenna->lnb_type==LNB_CTRL_STD)
    {
        //use forced H or V voltage,scan 1 time
        if(as_info->voltage_ctrl)
        {
            as_info->polar = antenna->pol - 1;
            loop = antenna->pol;
        }
        //use both H and V,scan 2 times
        else
        {
            as_info->polar = 0;
            loop = 2;
        }
    }
    //for pol controled 2-band lnb
    else if(antenna->lnb_type==LNB_CTRL_POL)
    {
        if(as_info->voltage_ctrl)
        {
            as_info->polar = antenna->pol - 1;
            loop = antenna->pol;
            //forced H voltage, scan IF from 950~1550 1 time
            if(as_info->polar==0)
    		{
        		to = 1550;
    		}
    		//Forced V Voltage, Scan IF 1551~2150 1 time
    		else if(as_info->polar == 1)
        	{
        		from = 1551;
    		}
	    }
        else
        {
            as_info->polar = 0;
            loop = 1;
        }
    }
    //for ku universal lnb
    else if((antenna->lnb_type==LNB_CTRL_22K)||(antenna->lnb_type==LNB_CTRL_UNICABLE))
    {
        if(as_info->voltage_ctrl)
        {
            as_info->polar = antenna->pol - 1;
            loop = antenna->pol;
        }
        else
        {
            as_info->polar = 0;
            loop = 2;
        }
        //firstly,scan low lnb to 22k_edge tp frq with 22k off
        antenna->k22 = 0;
        from = as_info->param.as_from;
    	if(antenna->lnb_low < antenna->lnb_high)
    	{
        	to = KU_LNB_22K_EDGE_FREQUENCY - antenna->lnb_low;
    	}
    	else
    	{
        	to = KU_LNB_22K_EDGE_FREQUENCY - antenna->lnb_high;
    	}
	}
    //scan loop  
    while(!as_info->stop_scan_signal)
    {
        for(; as_info->polar<loop; as_info->polar++)
        {
//            as_info->param.as_from = from;                  //Seiya Fix bug37335,universal lnb 4th times 
//            as_info->param.as_to = to;
    		if(as_info->stop_scan_signal)                     //scan lost 1950-2200 tp-s
    		{
        		break;   
    		}
            as_info->xponder.s_info.pol = as_info->polar;
            frontend_set_antenna(as_info->nim, antenna, &as_info->xponder, 1);
            osal_task_sleep(AS_TUNE_TIMEOUT_S);
            // make up the autoscan parameter list
            as_para->sfreq = from;
            as_para->efreq = to;
            as_para->callback = dvbs_as_callback;
	     #ifdef NIM_S3501_ASCAN_TOOLS  
		 //extern void nim_s3501_ascan_set_polar(UINT32 polar);
		 //nim_s3501_ascan_set_polar(as_info->polar);
		 extern nim_s3501_ascan_set_info(struct as_module_info *a_info);
		 nim_s3501_ascan_set_info(as_info);
	     #endif
            ret = nim_ioctl_ext(as_info->nim, NIM_DRIVER_AUTO_SCAN, as_para);
            if(ret!=SUCCESS)
    		{
        		break;
    		}
            dvbs_as_callback(AS_SGN_INIT, 0, 0, 0, 0);
        }
    	if (antenna->lnb_type==LNB_CTRL_UNICABLE && !as_info->dual_LNB) /* Unicable */		
		    break;	
        else if(ret||(antenna->k22==1)
            ||((antenna->lnb_type!=LNB_CTRL_22K)&&(antenna->lnb_type!=LNB_CTRL_UNICABLE)))
		{
            break;
		}
    	else
    	{
    		//Second, Scan High LNB from 22k_edge to 2150 TP Frequency with 22k On
    		antenna->k22 = 1;
            as_info->xponder.s_info.frq = KU_LNB_22K_EDGE_FREQUENCY+1;//switch to high band,turn on 22K
    		if(antenna->lnb_low < antenna->lnb_high)
    		{
        		from = KU_LNB_22K_EDGE_FREQUENCY - antenna->lnb_high;
    		}
    		else
    		{
        		from = KU_LNB_22K_EDGE_FREQUENCY - antenna->lnb_low;
    		}
            to = as_info->param.as_to;
            if(as_info->voltage_ctrl)
            {
                loop = antenna->pol;
                as_info->polar = antenna->pol - 1;
            }
            else
            {
                as_info->polar = 0;
                loop = 2;
            }
        }
    }
    
    return ret;
}

/*******dvbs blind scan*****************************************/


static INT32 as_enum_scan(UINT16 sat_id, UINT16 type, psi_tuning_t tuning_fn)
{
    BOOL db_ret = TRUE;
    INT32 ret = 0;
    INT32 func_ret = 0;
    UINT32 search_scheme;
    UINT8 lock_stat;
    struct as_tuning_param *atp = &as_info->atp;
    as_update_event_t update_event = as_info->param.as_handler;
    T_NODE t_node;
    BOOL syn_demod_lock_mode= FALSE;	
	 
    AS_PRINTF("start at %d\n", osal_get_tick());
    	
    if(update_event != NULL)
    {
       	update_event(ASM_TYPE_PROGRESS, AS_PROGRESS_SCANSTART+1);
    }

#if 0
	//Set First TP Info
    if(tuning_fn != NULL)
    {
       	tuning_fn(atp);
    }
#endif

	//TP Scan Loop
    while((atp->finish == FALSE) && (ret == 0))
    {
    	//The frontend turn to designated channel.
        if(tuning_fn != NULL)
        {
           	tuning_fn(atp);
        }
        if(atp->finish) //AutoScan finish search all TP.
            break;
    	//Set Search Scheme, that is whether Search NIT or not
       	search_scheme = as_info->param.as_prog_attr;
       	if (atp->nit_enable)
       	{
       		search_scheme |= P_SEARCH_NIT;
       	}

       	AS_PRINTF("id=%d, t_nr=%d\n",atp->tp_id, as_info->tp_nr);
       	lock_stat = 0;

	//Show New TP for DVB-S by Upper Layer
#if defined(STAR_PROG_SEARCH_NIT_SDT_SUPPORT)
       	if ((tuning_fn == as_dvbs_preset_tuning ||star_search_nit_staus==2) && (update_event))
#else
       	if ((tuning_fn == as_dvbs_preset_tuning) && (update_event))
#endif
       	{
        	update_event(ASM_TYPE_ADD_TRANSPONDER, atp->tp_id);
        }

		//Try to Lock Signal, may not need more time to wait demod lock here, as some demod was processed this in driver layer already.
		if(atp->ft_type == FRONTEND_TYPE_T)
		{
	            as_info->nim->do_ioctl(as_info->nim, NIM_DRIVER_GET_DEMOD_LOCK_MODE, (UINT32)&syn_demod_lock_mode);
		}
       	do
       	{
            nim_get_lock(as_info->nim, &lock_stat);
	        if((lock_stat) || (as_info->stop_scan_signal) ||syn_demod_lock_mode)
            {
                break;
            }
            osal_task_sleep(1);
        } while((INT32)osal_get_tick() < (INT32)atp->timeout);

		// fix a bug of 3501B tp scan, it need more time. (3501 SSI to SPI 8bit mode, for some coderate).
        if(atp->ft_type == FRONTEND_TYPE_S)
        {
            osal_task_sleep(1200);
        }

        AS_PRINTF("lock stat = %d\n", lock_stat);
        if (!as_info->stop_scan_signal)
        {
            //If Lock Signal, then Search Prog in this TP
            if (lock_stat)
            {
                //Scan from Start Frq to End Frq for DVB-C and DVB-T
                if (type == ATP_TYPE_STEP)
                {
                    //For DVB-C, Set TP Info according to as_info
                    if(as_info->param.as_frontend_type == FRONTEND_TYPE_C)
                    {
                        db_ret = dvbc_alloc_transponder(as_info, atp, &as_info->xp, sat_id);
                    }
					else if(as_info->param.as_frontend_type == FRONTEND_TYPE_T)
					{
                        db_ret = dvbt_alloc_transponder(as_info, atp, &as_info->xp, sat_id);
					}

					if (db_ret != TRUE)
                    {
                        ret = 1;
                        break;
                    }
					//Show New TP for DVB-C and DVB-T by Upper Layer
                    if(update_event)
                    {
                    #ifdef PUB_PORTING_PUB29
						update_event(ASM_TYPE_ADD_TRANSPONDER, 0xFFFE);//notify ap locked
                    #else
                    	update_event(ASM_TYPE_ADD_TRANSPONDER, atp->tp_id);//notify ap show tp
                    #endif
                    }
                }
                else if (type == ATP_TYPE_DBASE)
                {
                    #if(defined(POLAND_SPEC_SUPPORT)||defined(SUPPORT_FRANCE_HD))
                        if(as_info->param.as_frontend_type == FRONTEND_TYPE_T)
                        get_signal_of_tp(&as_info->xp);
                    #endif
                }
	 
#if defined(DVBT2_SUPPORT)
               do 
                {
#endif
    				//Prog Search in this TP
                    psi_module_init(as_info->dmx, as_info->nim, (void *)__MM_PSI_START_ADDR, __MM_PSI_BUF_LEN);
    			#ifdef COMBOUI
    				psi_set_search_ftype(as_info->param.as_frontend_type);
    			#endif
    				func_ret = psi_search_start(sat_id, atp->tp_id, search_scheme, as_info->param.as_p_add_cfg, psi_callback, NULL, NULL);
#if 0
    				func_ret = psi_search_start(sat_id, atp->tp_id, search_scheme, as_info->param.as_p_add_cfg, psi_callback, tuning_fn, atp);
#endif
                    if (SI_STOFULL == func_ret)
                    {
                    	ret= 1;
                    }
                #ifdef STAR_PROG_SEARCH_NIT_SDT_SUPPORT
    				else if(SI_EXIT_STAR == func_ret)
    				{
    					if((ATP_TYPE_DBASE == type))
    						as_info->stop_scan_signal = 1;
    				}
                #endif
#if defined(DVBT2_SUPPORT)
				}while( as_next_pipe_tuning(as_info, &as_info->xp) );
#endif		
                update_event(ASM_TYPE_ADD_TRANSPONDER, 0);//notify ap that finished search a TP.
            }
			//Not Lock Signal, then Switch to next TP
            else
            {

			#ifdef PUB_PORTING_PUB29
				if(update_event)
               	{
                   	update_event(ASM_TYPE_ADD_TRANSPONDER, 0xFFFF);//notify ap unlocked
               	}
			#endif
			#ifdef NIT_AUTO_SEARCH_SUPPORT
				if(tuning_fn== as_dvbc_blind_tuning && b_found_nit_tp)
				{// because doing auto scan,so atp->pos must > AS_MIN_CAB_FREQUENCY and we need to change to nit search.
					if(atp->pos > AS_MIN_CAB_FREQUENCY)
						atp->pos = 0;
					tuning_fn = as_dvbs_preset_tuning;
				}
			#endif
#if 0
            	tuning_fn(atp);
#endif            	
            }
        }
			
        if (as_info->stop_scan_signal || ret)
        {
        	break;
        }

		//Show Scan Progress by Upper Layer
#if defined(STAR_PROG_SEARCH_NIT_SDT_SUPPORT)
        if ((type == ATP_TYPE_DBASE) && (update_event))
#else
        if ((!as_info->tp_nit[0]) && (type == ATP_TYPE_DBASE) && (update_event))
#endif
        {
        	update_event(ASM_TYPE_PROGRESS, atp->pos*99/(as_info->tp_nr+2));
        }
    }
#ifdef NIT_AUTO_SEARCH_SUPPORT		
	b_found_nit_tp = FALSE; // nit search done
#endif	
    AS_PRINTF("end at %d\n", osal_get_tick());
    return ret;
}

#ifdef AUTO_OTA
#if(defined(DVBT_SUPPORT)||defined(ISDBT_SUPPORT)||defined(DVBC_SUPPORT))
/*******************************************************************************
*   Funtion name : as_scan_ssu_update()
*   Description:
*       1. scan ssu info in all freq.
*   Time: 20080418
*******************************************************************************/
#ifdef AUTO_OTA_DEBUG_PRINTF
#define AUTO_OTA_DEBUG		libc_printf
#else
#define AUTO_OTA_DEBUG(...) 	do{}while(0)
#endif
static void as_scan_ssu_update()
{
#if(defined(DVBT_SUPPORT)||(defined(ISDBT_SUPPORT)))
	si_scan_ssu_update_dvbt(&as_info->param, -1);
#endif
#ifdef DVBC_SUPPORT
	si_scan_ssu_update_dvbc(&as_info->param, -1);
#endif
}

INT32 as_otasearch_service_stop(BOOL bBlocking)
{
	return si_stop_channel_otasrch(bBlocking, -1);
}

INT32 f_as_otascan_dvbt(UINT32 sfreq, UINT32 efreq, UINT32 bandwidth, UINT8 band_type)//SN 20050623
{
	UINT32 ret = 0;
	T_NODE t_node;
	INT32 i = 0;
	UINT32 center_freq = 0;
	UINT32 lock = 0;
	UINT8 j = 0;     //HIER

	center_freq = sfreq + (bandwidth>>1);		

	static struct nim_device *lib_nim_dev=NULL;
	struct NIM_Channel_Change nim_param;
	//struct NIM_Channel_Search nim_param;
	UINT8 ota_guard_interval;
	UINT8 ota_fft_mode;
	UINT8 ota_modulation;
	UINT8 ota_FFC;
    UINT8 ota_inv;
	
    MEMSET(&nim_param, 0, sizeof(nim_param));
    
    nim_param.freq = center_freq;
	
    nim_param.bandwidth =  bandwidth/1000;
   
    nim_param.guard_interval = 0x4;
  
    nim_param.fft_mode = 0x2;

    nim_param.modulation = 0x4;
       		
    nim_param.fec = 0;
            	
    nim_param.usage_type = (UINT8)USAGE_TYPE_AUTOSCAN;
 
	
    nim_param.inverse = 1;
	//nim_param.freq_offset=500;

  	nim_param.priority = 0;
		            
	lib_nim_dev = (struct nim_device *)dev_get_by_id(HLD_DEV_TYPE_NIM, 0);
	if(lib_nim_dev!=NULL)
   		nim_io_control(lib_nim_dev, NIM_DRIVER_STOP_ATUOSCAN, 0);

	if(lib_nim_dev->do_ioctl_ext)
     {
         lock=lib_nim_dev->do_ioctl_ext(lib_nim_dev, NIM_DRIVER_CHANNEL_CHANGE, (void *)(&nim_param));
     }
	if (SUCCESS == lock)
	{
	      AUTO_OTA_DEBUG("enter:f_as_otascan_dvbt,\
	       and nim is lock\n");
		MEMSET(&t_node, 0, sizeof(T_NODE));

		t_node.sat_id = 0x1;
		t_node.frq = center_freq;
	    if (lib_nim_dev->get_guard_interval)
	    {
		t_node.guard_interval =lib_nim_dev->get_guard_interval(lib_nim_dev, &ota_guard_interval);
	    }
	
		if (lib_nim_dev->get_fftmode)
	    {
		t_node.FFT=lib_nim_dev->get_fftmode(lib_nim_dev, &ota_fft_mode);
	    }
		
		if (lib_nim_dev->get_modulation)
	    {
		t_node.modulation=lib_nim_dev->get_modulation(lib_nim_dev, &ota_modulation);
	    }
		
		t_node.bandwidth = bandwidth/1000;
		
		t_node.FEC_inner = api_nim_get_FEC();
		
		t_node.band_type = band_type;
		
		
		if (lib_nim_dev->get_spectrum_inv)
	    {
		t_node.inverse=lib_nim_dev->get_spectrum_inv(lib_nim_dev, &ota_inv);
	    }
       
		t_node.frq = api_nim_get_freq();   

#if(defined(SUPPORT_TP_QUALITY))
		UINT8 agc_buffer[5];
		UINT8 snr_buffer[5];
		UINT16 agc_sigma=0;
		UINT16 snr_sigma=0;
		//struct tp_info_t *tp_info = (struct tp_info_t *)__MM_SUB_BS_START_ADDR;			
		for(i=0;i<5;i++)
		{
			agc_buffer[i]=api_nim_get_AGC(); 
			snr_buffer[i]=api_nim_get_SNR(); 
			osal_task_sleep(5);	
			agc_sigma+=agc_buffer[i];
			snr_sigma+=snr_buffer[i];
		}
		t_node.intensity=agc_sigma/5;
		t_node.quality=snr_sigma/5;
#endif	
		psi_module_init((struct dmx_device *)dev_get_by_id(HLD_DEV_TYPE_DMX, 0),
			(struct nim_device *)dev_get_by_id(HLD_DEV_TYPE_NIM, 0), 
			(void *)__MM_PSI_START_ADDR, __MM_PSI_BUF_LEN);
		if (SI_STOFULL == psi_search_start(0x01, 
			t_node.tp_id, as_info->param.as_prog_attr, 
			as_info->param.as_p_add_cfg, 
			psi_callback, NULL, NULL)) {
			ret = !SUCCESS;
		}
	}
	else
		ret = !SUCCESS;
	AUTO_OTA_DEBUG("ret=%d\n",ret);
	return ret;	
}
INT32 f_as_otascan_dvbc(UINT32 sfreq,UINT32 step,UINT32 symbol,UINT8 modulation,UINT8 bandtype)
{
	UINT32 ret = 0;
	T_NODE t_node;
	INT32 i = 0;
	UINT32 center_freq = 0;
	UINT32 lock = 0;
	 
	
	center_freq = sfreq + (step>>1);

	static struct nim_device *lib_nim_dev=NULL;
	struct NIM_Channel_Change cc_nim_param;
	UINT8 ota_guard_interval;
	UINT8 ota_fft_mode;
	UINT8 ota_modulation;
	UINT8 ota_FFC;
    UINT8 ota_inv;
	
    MEMSET(&cc_nim_param, 0, sizeof(cc_nim_param));
    
    cc_nim_param.freq = center_freq;
	cc_nim_param.sym=symbol;
    cc_nim_param.bandwidth =step/1000;
    		
    cc_nim_param.modulation = modulation;
        
	lib_nim_dev = (struct nim_device *)dev_get_by_id(HLD_DEV_TYPE_NIM, 0);
   	

	if(lib_nim_dev->do_ioctl_ext)
     {
         lock=lib_nim_dev->do_ioctl_ext(lib_nim_dev, NIM_DRIVER_CHANNEL_CHANGE, (void *)(&cc_nim_param));
     }

	if (SUCCESS == lock)
	{
		MEMSET(&t_node, 0, sizeof(T_NODE));

		t_node.sat_id = 0x1;
		t_node.frq = center_freq;
		
		
	  
	    if (lib_nim_dev->get_guard_interval)
	    {
		t_node.guard_interval =lib_nim_dev->get_guard_interval(lib_nim_dev, &ota_guard_interval);
	    }
	
		if (lib_nim_dev->get_fftmode)
	    {
		t_node.FFT=lib_nim_dev->get_fftmode(lib_nim_dev, &ota_fft_mode);
	    }
		
		if (lib_nim_dev->get_modulation)
	    {
		t_node.modulation=lib_nim_dev->get_modulation(lib_nim_dev, &ota_modulation);
	    }
		
		t_node.bandwidth = step/1000;
		
		t_node.FEC_inner = api_nim_get_FEC();
		
		t_node.band_type = bandtype;
		
		
		if (lib_nim_dev->get_spectrum_inv)
	    {
		t_node.inverse=lib_nim_dev->get_spectrum_inv(lib_nim_dev, &ota_inv);
	    }
       
		t_node.frq = api_nim_get_freq();   
		
/*
		lock = api_nim_channel_search(center_freq, bandwidth/1000, 0x4, 0x2, 0x4, 0, 0, 1,500, 0);
	if (SUCCESS == lock)
	{
		MEMSET(&t_node, 0, sizeof(T_NODE));

		t_node.sat_id = 0x1;
		t_node.frq = center_freq;
	    t_node.guard_interval = api_nim_get_gi();
		t_node.FFT = api_nim_get_fftmode();
		t_node.modulation = api_nim_get_modulation();
		t_node.bandwidth = bandwidth/1000;
		t_node.FEC_inner = api_nim_get_FEC();
		t_node.band_type = band_type;
		t_node.inverse = api_nim_get_freqinv(); //default for test, SN 20050524

		t_node.frq = api_nim_get_freq();   //SN for nim to get the real freq, 20050524

*/
#if(defined(SUPPORT_TP_QUALITY))
		UINT8 agc_buffer[5];
		UINT8 snr_buffer[5];
		UINT16 agc_sigma=0;
		UINT16 snr_sigma=0;
		//struct tp_info_t *tp_info = (struct tp_info_t *)__MM_SUB_BS_START_ADDR;			
		for(i=0;i<5;i++)
		{
			agc_buffer[i]=api_nim_get_AGC(); 
			snr_buffer[i]=api_nim_get_SNR(); 
			osal_task_sleep(5);	
			agc_sigma+=agc_buffer[i];
			snr_sigma+=snr_buffer[i];
		}
		t_node.intensity=agc_sigma/5;
		t_node.quality=snr_sigma/5;
#endif	
		psi_module_init((struct dmx_device *)dev_get_by_id(HLD_DEV_TYPE_DMX, 0),
			(struct nim_device *)dev_get_by_id(HLD_DEV_TYPE_NIM, 0), 
			(void *)__MM_PSI_START_ADDR, __MM_PSI_BUF_LEN);
		if (SI_STOFULL == psi_search_start(0x01, 
			t_node.tp_id, as_info->param.as_prog_attr, 
			as_info->param.as_p_add_cfg, 
			psi_callback, NULL, NULL)) {
			ret = !SUCCESS;
		}
	}
	else
		ret = !SUCCESS;
		
	return ret;	
}

UINT16 get_region_ch_num()
{
	UINT16 total_cnt =0;
	UINT8 i;
	if(as_info->param.as_method != AS_METHOD_FFT)
		return 1;
	for(i=0;i<MAX_BAND_COUNT;i++)
	{
		if(((as_info->param.band_group_param+i)->start_freq)!=0)
		{
			total_cnt+= ((as_info->param.band_group_param+i)->end_freq - (as_info->param.band_group_param+i)->start_freq)/ \
				(as_info->param.band_group_param+i)->bandwidth;
		}
		else
			break;
	}
	return total_cnt;
}
#endif
#endif
static INT32 as_scan(UINT16 sat_id, S_NODE *sat, INT32 method, BOOL cached)
{
    INT32 ret=0;
    UINT8 prog_mode;
   
	//Set Program Mode
	if((as_info->param.as_method == AS_METHOD_NVOD)
        	||(as_info->param.as_method == AS_METHOD_NVOD_MULTI_TP))
	{
    	prog_mode = PROG_NVOD_MODE;
	}
	else if(as_info->param.as_method == AS_METHOD_DATA)
	{
    	prog_mode = PROG_DATA_MODE;
	}
	else
	{
    	prog_mode = PROG_ALL_MODE;
	}

	//Create Program View
    db_search_create_pg_view(TYPE_SAT_NODE, sat_id, prog_mode);
//#ifdef ITALY_HD_BOOK_SUPPORT
#if(defined ITALY_HD_BOOK_SUPPORT ||defined 	POLAND_SPEC_SUPPORT)	
	if(NodeView_InitCallback)
		NodeView_InitCallback();
#endif

	//Blind Scan
    if (AS_METHOD_FFT == method)
    {
    	if(as_info->param.as_frontend_type == FRONTEND_TYPE_S)
    	{
    		#ifdef NIM_S3501_ASCAN_TOOLS
			extern UINT32 nim_s3501_ascan_get_loop_cnt();
			extern void nim_s3501_ascan_clear_loop_cur_idx();
			extern INT32 nim_s3501_ascan_start_process();
			extern INT32 nim_s3501_ascan_end_process();
			UINT32 t_loop=nim_s3501_ascan_get_loop_cnt();
			int i=0;
			nim_s3501_ascan_clear_loop_cur_idx();
			
			for(i=0x00;i<t_loop;i++)
			{
				nim_s3501_ascan_start_process();
		#endif
        	ret = as_dvbs_blind_scan(&as_info->antenna);
		#ifdef NIM_S3501_ASCAN_TOOLS
				if(ret != SUCCESS)
					break;
				if(as_info->stop_scan_signal)
					break;
				nim_s3501_ascan_end_process();
			}
		#endif
    	}
        else if(as_info->param.as_frontend_type == FRONTEND_TYPE_C)
        {
#ifdef DVBC_COUNTRY_BAND_SUPPORT
			c_srh_tp_step = 0;
			dvbc_bs_freq_end = 0;
#endif
			if (dvbc_init_search_param(&as_info->atp, &as_info->param) == FALSE)
           // if (dvbc_init_search_param(&as_info->atp, as_info->param.as_from, as_info->param.as_to) == FALSE)
            {
            	return -1;
            }
            ret = as_enum_scan(sat_id, ATP_TYPE_STEP, as_dvbc_blind_tuning);
        }
        else if((as_info->param.as_frontend_type==FRONTEND_TYPE_T))
        {
			if(dvbt_init_search_param(&as_info->param, &as_info->atp)==FALSE)
				return -1;
			ret = as_enum_scan(sat_id, ATP_TYPE_STEP, as_dvbt_blind_tuning);
        }
    }
    else
    {
    	MEMSET(&(as_info->atp), 0, sizeof(struct as_tuning_param));
		if((as_info->param.as_frontend_type==FRONTEND_TYPE_T))
	    {
			as_info->atp.ft_type = FRONTEND_TYPE_T;
	    }	
    	ret = as_enum_scan(sat_id, ATP_TYPE_DBASE, as_dvbs_preset_tuning);
	}

	//Process by Upper Layer
	if ((1 == ret) && (as_info->param.as_handler))
	{
    	as_info->param.as_handler(ASM_TYPE_PROGRESS, AS_PROGRESS_STOFULL);
	}

    return ret;
}

/* description	: auto scan main routine for command parsing and switching.*/
static void as_main(struct libpub_cmd *cmd)
{
    INT32 i, j;
    INT32 ret;
    INT32 method;
    INT32 tp_nr;
    INT32 as_method;
    UINT16 sat_id;
    UINT8 dmx_mode_need_resume = 0;
    UINT32 dmx_dma_mode;
    as_update_event_t event_handler;
    struct dmx_device *dmx = NULL;
    T_NODE *tp = &as_info->cur_tp;;
    S_NODE *sat = &as_info->cur_sat;
    struct ft_antenna *antenna = &as_info->antenna;	
    
    AS_PRINTF("start time stamp = %d\n", osal_get_tick());
    as_method = as_info->param.as_method;
	
    event_handler = as_info->param.as_handler;
#ifdef AUTO_OTA
#if(defined(DVBT_SUPPORT)||defined(ISDBT_SUPPORT)||defined(DVBC_SUPPORT))
    if(as_method == AS_METHOD_SSU_SEARCH)
    {
    }
    else
#endif 
#endif 
	if(event_handler!=NULL)
	{
    	event_handler(ASM_TYPE_PROGRESS, AS_PROGRESS_SCANSTART);
	}

	//Select DMX
	dmx = dev_get_by_id(HLD_DEV_TYPE_DMX, 0);
	if(dmx == NULL)
	{
        AS_PRINTF("%s(): select dmx failed!\n");
    	return;
	}
	as_info->dmx = dmx;
        
	//fix BUG20874: init psi info to avoid dmx changed by video playing
	psi_info_init(as_info->dmx, as_info->nim, (void *)__MM_PSI_START_ADDR, __MM_PSI_BUF_LEN);
	//Check and Switch Buffer Mode of Dmx (From Divided Buffer To Union Buffer)
	dmx_io_control(as_info->dmx, DMX_CHK_BUF_MODE, (UINT32)&dmx_dma_mode);
	if(dmx_dma_mode == DMX_DIVIDED_BUFF_MODE)
	{
    	dmx_io_control(as_info->dmx, DMX_SWITCH_TO_UNI_BUF, 0);
    	dmx_mode_need_resume = 1;
	}
#ifdef AUTO_OTA
#if(defined(DVBT_SUPPORT)||defined(ISDBT_SUPPORT)||defined(DVBC_SUPPORT))
    if(as_method == AS_METHOD_SSU_SEARCH)
    {
        i =0;//set tsi for failure of ota scan when there is no program.
        //For Each Satellite, Create its TP View, Set Antenna
        sat_id = as_info->sat_id[i];
        db_search_create_tp_view(sat_id);

		//Set Antenna Information according to Satellite Information
        MEMSET(sat, 0, sizeof(S_NODE));
        get_sat_by_id(sat_id, sat);
//#ifdef PUB_PORTING_PUB29
		//if(as_info->param.as_frontend_type==FRONTEND_TYPE_T)
		//	sat->sat_id = 1;
//#endif
		AS_DUMP_SAT(sat);
		MEMSET(antenna, 0, sizeof(struct ft_antenna));
		sat2antenna(sat, antenna);
		
        as_info->dual_LNB = (antenna->lnb_high>0) && (antenna->lnb_low>0) && (antenna->lnb_high != antenna->lnb_low);
        as_info->voltage_ctrl = (antenna->pol==LNB_POL_H)||(antenna->pol==LNB_POL_V);
//>>> Unicable begin
        if(antenna->lnb_type == LNB_CTRL_UNICABLE)
        {
    	    as_info->nim_para.unicable = 1;
    	    as_info->nim_para.Fub = antenna->unicable_freq;
        } 
        else
    	    as_info->nim_para.unicable = 0; 
//<<< Unicable end
        //select right nim and dmx    
        as_select_nim(sat, as_info->param.as_frontend_type);

	 	//for 29E 2-Tuner the dmx path may not same as default!!
	 	tsi_dmx_src_select(TSI_DMX_0, TSI_TS_A);
     
        as_scan_ssu_update();
    	as_info->param.as_handler(SI_OTA_SEARCH_OVER, 0);
        //libc_printf("ota auto search end!!");
    }
    else{
#endif     	
#endif
	for(i = 0; i<as_info->sat_nr; i++)
	{
    	//For Each Satellite, Create its TP View, Set Antenna
    	sat_id = as_info->sat_id[i];
    	db_search_create_tp_view(sat_id);
	
    	if(event_handler != NULL)
    	{
        	event_handler(ASM_TYPE_SATELLITE, sat_id);
    	}

	    //Set Antenna Information according to Satellite Information
    	MEMSET(sat, 0, sizeof(S_NODE));
    	get_sat_by_id(sat_id, sat);
//#ifdef PUB_PORTING_PUB29
		if(as_info->param.as_frontend_type==FRONTEND_TYPE_T)
			sat->sat_id = 1;
//#endif
    	AS_DUMP_SAT(sat);
    	MEMSET(antenna, 0, sizeof(struct ft_antenna));
        if(as_info->param.as_frontend_type == FRONTEND_TYPE_S)
        {
    	    sat2antenna(sat, antenna);	
    	    as_info->dual_LNB = (antenna->lnb_high>0) && (antenna->lnb_low>0) && (antenna->lnb_high != antenna->lnb_low);
            as_info->voltage_ctrl = (antenna->pol==LNB_POL_H)||(antenna->pol==LNB_POL_V);
        
            //>>> Unicable begin
            if(antenna->lnb_type == LNB_CTRL_UNICABLE)
            {
        	    as_info->nim_para.unicable = 1;
        	    as_info->nim_para.Fub = antenna->unicable_freq;
            } 
            else
        	    as_info->nim_para.unicable = 0;        
        }
        //<<< Unicable end
        //select right nim and dmx    
        as_select_nim(sat, as_info->param.as_frontend_type);
        if(as_info->nim ==NULL)
        {
            AS_PRINTF("%s(): select nim failed!\n");
            continue;
        }

    	 //for 29E 2-Tuner the dmx path may not same as default!!
    	 tsi_dmx_src_select(TSI_DMX_0, TSI_TS_A);
    
        //blind scan
        if((AS_METHOD_FFT==as_method)||(AS_METHOD_MULTI_FFT==as_method))
        {
            method = AS_METHOD_FFT;
        }
        else
        {
            as_info->tp_nr = 0;
            MEMSET(as_info->tp_nit, 0,AS_MODULE_MAX_T_NUM*sizeof(UINT8));
            //single tp scan
            if((AS_METHOD_TP==as_method)||(AS_METHOD_TP_PID==as_method)
                ||(AS_METHOD_NIT_TP==as_method)||(AS_METHOD_NVOD==as_method)||(AS_METHOD_FREQ_BW==as_method))
            {
                as_info->tp_nr = 1;
				
                as_info->tp_id[0] = as_info->param.as_from;
                if ((AS_METHOD_NIT_TP==as_method)&&(event_handler!=NULL))
        		{
            		event_handler(ASM_TYPE_INC_TRANSPONDER, 0);
        		}
            }
            //multi tp scan
            else if((AS_METHOD_SAT_TP==as_method)||(AS_METHOD_NIT==as_method)
                ||(AS_METHOD_MULTI_TP==as_method)||(AS_METHOD_MULTI_NIT==as_method)
                ||(AS_METHOD_NVOD_MULTI_TP==as_method))
            {
                tp_nr = get_tp_num_sat(sat_id);
                for(j=0; j<tp_nr; j++)
                {
                    get_tp_at(sat_id, j, tp);
                    if(as_info->param.as_frontend_type==FRONTEND_TYPE_S)
                    {
                        if(dvbs_tp_sanity_check(as_info->voltage_ctrl,tp, sat)==FALSE)
        			 	{
                			continue;
        			 	}
        			}
        			else if(as_info->param.as_frontend_type == FRONTEND_TYPE_C)
        			{
               			if(dvbc_tp_sanity_check(FALSE, tp, NULL) == FALSE)
               			{
                    			continue;
               			}
        			}
                    
                    AS_DUMP_TP(tp);
#ifdef NVOD_FEATURE
                    if((AS_METHOD_NVOD_MULTI_TP == as_method) && (tp->nvod_flg == 1))
#endif
					{
                    	as_info->tp_id[as_info->tp_nr++] = tp->tp_id;
					}

        			if (AS_MODULE_MAX_T_NUM == as_info->tp_nr)
        			{
            			AS_PRINTF("%s: tp exceed AS_MODULE_MAX_T_NUM!\n", __FUNCTION__);
        			}
        		}
            }

	        if((AS_METHOD_NIT==as_method)||(AS_METHOD_NIT_TP==as_method)
                ||(AS_METHOD_MULTI_NIT==as_method))
            {
                MEMSET(as_info->tp_nit, 1, as_info->tp_nr);
            }
            	
            method = AS_METHOD_TP;
        }

        ret = as_scan(sat_id, sat, method, 0);
        
        update_data( );

    	//if (ret || as_info->stop_scan_signal)
    	if(as_info->stop_scan_signal)     //solve the bug:if the first nim is error,won't scan the second nim
    	{
        	break;
    	}
	}

    //Show Scan Over by Upper Layer
	if(event_handler != NULL)
	{
    	event_handler(ASM_TYPE_PROGRESS, AS_PROGRESS_SCANOVER);
	}
#ifdef AUTO_OTA
#if(defined(DVBT_SUPPORT)||defined(ISDBT_SUPPORT)||defined(DVBC_SUPPORT))
    }
#endif
#endif   

	dmx_io_control(as_info->dmx, CLEAR_STOP_GET_SECTION, 0);
    //Switch Buffer Mode of Dmx (From Union Buffer to Divided Buffer)
	if(dmx_mode_need_resume)
	{
    	dmx_io_control(as_info->dmx, DMX_SWITCH_TO_DVI_BUF, 0);
	}
	sie_open(as_info->dmx, MAX_FILTER_NUMBER, NULL, 0);
     
    osal_task_dispatch_off();
    nim_io_control(as_info->nim, NIM_DRIVER_STOP_ATUOSCAN, 0);
    as_info = NULL;
    AS_PRINTF("end time stamp = %d\n", osal_get_tick());
    osal_task_dispatch_on();
}


/*description	: register auto-scan service task, but not run it.*/
INT32 as_service_register()
{
    libpub_cmd_handler_register(LIBPUB_CMD_AS, as_main);
    return SUCCESS;
}


/*description	: start an auto-scan according to the parameter asp.*/
INT32 as_service_start(struct as_service_param *asp)
{
    struct libpub_cmd cmd;

    if (as_info != NULL)
        return 0;

#ifndef __MM_VBV_START_ADDR
	if(NULL == as_buf)
	{
		as_buf = MALLOC(AS_BUF_LEN);
	}
#endif	
		
#if defined(STAR_PROG_SEARCH_NIT_SDT_SUPPORT)
	star_search_nit_staus = 0;
#endif
		
    as_info = (struct as_module_info *)__MM_AS_START_ADDR;
    MEMSET(as_info, 0, sizeof(struct as_module_info));
    MEMCPY(&as_info->param, asp, sizeof(struct as_service_param));
    as_info->param.as_prog_attr |= P_SEARCH_SATTP;

    if(asp->as_frontend_type==FRONTEND_TYPE_S)
    	{
        	dvbs_as_callback(AS_SGN_INIT, 0, 0, 0, 0);
    	}
	else if(asp->as_frontend_type == FRONTEND_TYPE_T )
	{

	}
	    
    as_info->sat_nr = asp->as_sat_cnt;

	if(as_info->sat_nr > AS_MODULE_MAX_S_NUM)
		as_info->sat_nr = AS_MODULE_MAX_S_NUM;

    MEMCPY(as_info->sat_id, asp->sat_ids,as_info->sat_nr*sizeof(UINT16));
 
    cmd.cmd_type = LIBPUB_CMD_AS_START;	
    return libpub_send_cmd(&cmd, OSAL_WAIT_FOREVER_TIME);
	
}

/* API for Stop Auto Scan */
INT32 as_service_stop()
{
    struct nim_device *nim = NULL;
    
    osal_task_dispatch_off();
    if (as_info != NULL)
    {
       	as_info->stop_scan_signal = 1;
		if(as_info->nim!=NULL)
		{
			nim = as_info->nim;
     		nim_io_control(nim, NIM_DRIVER_STOP_ATUOSCAN, 1);
		}
    }
    osal_task_dispatch_on();

    if (as_info != NULL)
    {
       	psi_search_stop();//stop getting psi section
    }

    while (as_info)
    	osal_task_sleep(AS_MODULE_SLEEP_SLICE);

#ifndef __MM_VBV_START_ADDR
	if(NULL != as_buf)
	{
		FREE(as_buf);
		as_buf = NULL;
	}		
#endif

    return SUCCESS;
}


/*description	: return ERR_BUSY when in scan mode.*/
INT32 as_service_query_stat()
{
    return (NULL == as_info)? SUCCESS: ERR_BUSY;
}


/*search for special program that not listed in PAT,PMT,SDT,
* input the video,audio,pcr pids, dmx will check if there is probably such a prog in current TS. 
*/
BOOL as_prog_pid_search(struct dmx_device *dmx,UINT8 av_mode,
UINT16 v_pid, UINT16 a_pid,UINT16 pcr_pid)
{
    UINT16 pid_list[3];
    struct io_param io_param;
    BOOL ret = FALSE;
   
    if(av_mode != 1)
    {
    	return FALSE;
    }
    
    if(dmx == NULL)
    {
    	return FALSE;
    }
		
    pid_list[0] = v_pid;
    pid_list[1] = a_pid;
    pid_list[2] = pcr_pid;
    io_param.io_buff_in = (UINT8 *)pid_list;	
	io_param.buff_in_len = sizeof(pid_list);
    if(dmx_io_control(dmx, IO_CREATE_AV_STREAM, (UINT32)&io_param) == RET_SUCCESS)
    {
       	if(dmx_io_control(dmx, IO_STREAM_ENABLE, (UINT32)&io_param) == RET_SUCCESS)
       	{
            UINT32 tmo = 6;
            while(tmo)
            {
				osal_task_sleep(100);
                tmo--;
                if(dmx_io_control(dmx, IS_PROGRAM_LEGAL, (UINT32)&io_param) == RET_SUCCESS)
                {
                	ret = TRUE;
                    break;
                }
            }
        }
    }

    dmx_io_control(dmx, IO_STREAM_DISABLE, (UINT32)&io_param);

    return ret;
}
//#ifdef ITALY_HD_BOOK_SUPPORT
#if(defined ITALY_HD_BOOK_SUPPORT ||defined POLAND_SPEC_SUPPORT)	
void node_View_inital_registor(BOOL (*node_view_inital_callback)())
{
	NodeView_InitCallback = node_view_inital_callback;
}
#endif


